package com.qinggeng.project.system.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qinggeng.common.enums.OrdersDistTypeEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.utils.DateUtils;
import com.qinggeng.project.api.dto.DateDto;
import com.qinggeng.project.api.dto.DistributionPointDto;
import com.qinggeng.project.api.dto.TimeDto;
import com.qinggeng.project.api.utils.AMapUtils;
import com.qinggeng.project.system.domain.*;
import com.qinggeng.project.system.domain.json.DistTime;
import com.qinggeng.project.system.mapper.DistributionConfigMapper;
import com.qinggeng.project.system.mapper.DistributionPointMapper;
import com.qinggeng.project.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author WangKh
 * @date 2019-11-15
 */
@Service
public class DistributionConfigServiceImpl implements DistributionConfigService {


    private static final long nd = 1000 * 24 * 60 * 60;

    @Resource
    private DistributionConfigMapper distributionConfigMapper;

    @Autowired
    private ISysRegionService sysRegionService;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private IShopService shopService;
    @Autowired
    private OrdersDistService ordersDistService;

    @Resource
    private DistributionPointMapper distributionPointMapper;


    @Override
    public List<DistributionConfig> queryDistributionConfigList(DistributionConfig distributionConfig) {
        return distributionConfigMapper.selectDistributionConfigList(distributionConfig);
    }

    @Override
    public DistributionConfig findDistributionConfigById(Long id) {
        return distributionConfigMapper.selectDistributionConfigById(id);
    }

    @Override
    @Transactional
    public int createDistributionConfig(DistributionConfig distributionConfig) {
        return distributionConfigMapper.insertDistributionConfig(distributionConfig);
    }

    @Override
    @Transactional
    public int updateDistributionConfig(DistributionConfig distributionConfig) {
        return distributionConfigMapper.updateDistributionConfig(distributionConfig);
    }

    @Override
    @Transactional
    public int deleteDistributionConfigById(Long id) {
        return distributionConfigMapper.deleteDistributionConfigById(id);
    }

    @Override
    @Transactional
    public int createDistributionConfigAll(List<DistributionConfig> data, Long regionId) {
        if (data.size() > 0) {
            distributionConfigMapper.delectAllConfig(regionId);
            for (DistributionConfig distributionConfig : data) {
                distributionConfig.setRegionId(regionId);
                distributionConfigMapper.insertDistributionConfig(distributionConfig);
            }
            return 1;
        } else {
            return 0;
        }
    }

    @Override
    public BigDecimal calcDistPrice(Float lng, Float lat, Double distance, String distTime) throws Exception{
        BigDecimal distPrice = new BigDecimal(0);

        List<DistributionConfig> distributionConfigList = getDistributionConfig(lng,lat);

       /* String[] currentSplit = distTime.split(":");
        int currentTime = Integer.valueOf(currentSplit[0]) * 3600 + Integer.valueOf(currentSplit[1]) * 60;
        String[] minSplit,maxSplit = null;
        int minTime,maxTime = 0;*/
        for (DistributionConfig distributionConfig : distributionConfigList) {
            //基础运费 设置
            if (distributionConfig.getType().equals("00")){
                distPrice = distPrice.add(distributionConfig.getPrice());
            }
            //距离费用
            if (distributionConfig.getType().equals("10")){
                if (distance.intValue() > Double.parseDouble(distributionConfig.getMin())){
                    distPrice = distPrice.add(distributionConfig.getPrice());
                }
            }
            //时间运费
            /*if (distributionConfig.getType().equals("30")){
                minSplit = distributionConfig.getMin().split(":");
                minTime = Integer.valueOf(minSplit[0]) * 3600 + Integer.valueOf(minSplit[1]) * 60;
                maxSplit = distributionConfig.getMax().split(":");
                maxTime = Integer.valueOf(maxSplit[0]) * 3600 + Integer.valueOf(maxSplit[1]) * 60;
                if (currentTime > minTime || currentTime < maxTime){
                    discPrice = discPrice.add(distributionConfig.getPrice());
                }
            }*/
        }
        return distPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    @Override
    public BigDecimal calcDateTimePrice(Float lng, Float lat,String distTime) throws Exception {
        BigDecimal discPrice = new BigDecimal(0);
        List<DistributionConfig> distributionConfigList = getDistributionConfig(lng,lat);

        String[] currentSplit = distTime.split(":");
        int currentTime = Integer.valueOf(currentSplit[0]) * 3600 + Integer.valueOf(currentSplit[1]) * 60;
        String[] minSplit,maxSplit = null;
        int minTime,maxTime = 0;

        for (DistributionConfig distributionConfig : distributionConfigList) {
            //时间运费
            if (distributionConfig.getType().equals("30")){
                minSplit = distributionConfig.getMin().split(":");
                minTime = Integer.valueOf(minSplit[0]) * 3600 + Integer.valueOf(minSplit[1]) * 60;
                maxSplit = distributionConfig.getMax().split(":");
                maxTime = Integer.valueOf(maxSplit[0]) * 3600 + Integer.valueOf(maxSplit[1]) * 60;
                if (currentTime > minTime || currentTime < maxTime){
                    discPrice = discPrice.add(distributionConfig.getPrice());
                }
            }
        }
        return discPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    @Override
    public List<DistributionConfig> getDistributionConfig(Float lng, Float lat) throws Exception{
        JSONObject geocodeRegeoObject = AMapUtils.geocodeRegeo(lng + "," + lat);

        JSONObject addressComponentObject = geocodeRegeoObject.getJSONObject("regeocode").getJSONObject("addressComponent");

        SysRegion provinceRegion = sysRegionService.selectSysRegionByName(addressComponentObject.getString("province"), 1);
        SysRegion cityRegion = sysRegionService.selectSysRegionByName(addressComponentObject.getString("city"), 2);
        SysRegion districtRegion = sysRegionService.selectSysRegionByName(addressComponentObject.getString("district"), 3);

        DistributionConfig where = new DistributionConfig();
        where.setRegionId(districtRegion.getId());
        List<DistributionConfig> distributionConfigList = distributionConfigMapper.selectDistributionConfigList(where);
        if (distributionConfigList.size() <= 0){
            where.setRegionId(cityRegion.getId());
            distributionConfigList = distributionConfigMapper.selectDistributionConfigList(where);
            if (distributionConfigList.size() <= 0){
                where.setRegionId(provinceRegion.getId());
                distributionConfigList = distributionConfigMapper.selectDistributionConfigList(where);
                if (distributionConfigList.size() <= 0){
                    where.setRegionId(0l);
                    distributionConfigList = distributionConfigMapper.selectDistributionConfigList(where);
                }
            }
        }
        if (distributionConfigList.size() <= 0){
            throw new CustomException("配送费规则未定义");
        }
        return distributionConfigList;
    }

    public List<DateDto> getDistributionDateList(Shop shop, DistributionPointDto pointDto) {
        //所属商户
        if (shop == null) {
            throw new CustomException("商户不存在");
        }
        if(pointDto==null){
            throw new CustomException("配送点不存在");
        }
        //自取时间列表集合
        List<DateDto> dateDtoList = Lists.newArrayList();
        String[] weekArray = {"星日", "周一", "周二", "周三", "周四", "周五", "周六"};

        //上午自取时间段
        TimeDto morning = new TimeDto();
        morning.setStartTime(pointDto.getBusinessTime());//设置营业时间
        morning.setEndTime("12:00");
        //下午自取时间段
        TimeDto afternoon=new TimeDto();
        afternoon.setStartTime("14:00");
        afternoon.setEndTime(pointDto.getClosingTime());//设置打烊时间

        //获取距离
        Double distance=AMapUtils.getDistance(pointDto.getLat(),pointDto.getLng(),shop.getLat(),shop.getLng())/1000;
        Date arriveTime=getDistributionDate(distance,OrdersDistTypeEnum.自取.getValue());
        //用户自取时间
        Calendar pickCalendar = Calendar.getInstance();
        int dayCount = 0;
        do {
            //自取时间为下午14:00
            pickCalendar.set(Calendar.HOUR_OF_DAY,14);
            //自取时间晚于商品到达时间，即商品已到达，可自取
            if(pickCalendar.getTime().after(arriveTime)){
                DateDto dateTimeDto = new DateDto();
                dateTimeDto.setDayTime(DateUtils.parseDateToStr("MM月dd日", pickCalendar.getTime()));
                dateTimeDto.setDayName( "[" + weekArray[pickCalendar.get(Calendar.DAY_OF_WEEK) - 1] + "]");
                //自取时间为上午
                Integer hour=Integer.parseInt(pointDto.getBusinessTime().split(":")[0]);
                pickCalendar.set(Calendar.HOUR_OF_DAY,hour);
                /**
                 * dateTimeDto设置timeList属性
                 */
                List<TimeDto> timeList = new ArrayList<>();
                if(pickCalendar.getTime().after(arriveTime)){
                    timeList.add(morning);
                }
                timeList.add(afternoon);
                dateTimeDto.setTimeList(timeList);
                //添加到自取时间列表集合中
                dateDtoList.add(dateTimeDto);
                dayCount++;
            }
            //往后添加一天
            pickCalendar.add(Calendar.DATE,1);
        } while (dayCount<3);
        return dateDtoList;
    }
    @Override
    public List<DateDto> getDistributionDateList(Shop shop, DistributionPoint point) {
        //所属商户
        if (shop == null) {
            throw new CustomException("商户不存在");
        }
        if(point==null){
            throw new CustomException("配送点不存在");
        }
        //自取时间列表集合
        List<DateDto> dateDtoList = Lists.newArrayList();
        String[] weekArray = {"星日", "周一", "周二", "周三", "周四", "周五", "周六"};

        //上午自取时间段
        TimeDto morning = new TimeDto();
        morning.setStartTime(point.getBusinessTime());//设置营业时间
        morning.setEndTime("12:00");
        //下午自取时间段
        TimeDto afternoon=new TimeDto();
        afternoon.setStartTime("14:00");
        afternoon.setEndTime(point.getClosingTime());//设置打烊时间

        //获取距离
        Double distance=AMapUtils.getDistance(point.getLat(),point.getLng(),shop.getLat(),shop.getLng())/1000;
        Date arriveTime=getDistributionDate(distance,OrdersDistTypeEnum.自取.getValue());
        //用户自取时间
        Calendar pickCalendar = Calendar.getInstance();
        int dayCount = 0;
        do {
            //自取时间为下午14:00
            pickCalendar.set(Calendar.HOUR_OF_DAY,14);
            //自取时间晚于商品到达时间，即商品已到达，可自取
            if(pickCalendar.getTime().after(arriveTime)){
                DateDto dateTimeDto = new DateDto();
                dateTimeDto.setDayTime(DateUtils.parseDateToStr("MM月dd日", pickCalendar.getTime()));
                dateTimeDto.setDayName( "[" + weekArray[pickCalendar.get(Calendar.DAY_OF_WEEK) - 1] + "]");
                //自取时间为上午
                Integer hour=Integer.parseInt(point.getBusinessTime().split(":")[0]);
                pickCalendar.set(Calendar.HOUR_OF_DAY,hour);
                /**
                 * dateTimeDto设置timeList属性
                 */
                List<TimeDto> timeList = new ArrayList<>();
                if(pickCalendar.getTime().after(arriveTime)){
                    timeList.add(morning);
                }
                timeList.add(afternoon);
                dateTimeDto.setTimeList(timeList);
                //添加到自取时间列表集合中
                dateDtoList.add(dateTimeDto);
                dayCount++;
            }
            //往后添加一天
            pickCalendar.add(Calendar.DATE,1);
        } while (dayCount<3);
        return dateDtoList;
    }

    @Override
    public String getDistDateTime() {
        Date distTime=getDistributionDate(null,OrdersDistTypeEnum.配送.getValue());
        String[] dayNames={"今天","明天","后天"};
        String dateTime=DateUtils.parseDateToStr("MM月dd日",distTime);
        //获取订单的配送时间与当天时间的日期差
        Calendar today=Calendar.getInstance();
        today.set(Calendar.HOUR_OF_DAY,0);
        today.set(Calendar.MINUTE,0);
        today.set(Calendar.SECOND,0);
        int day = (int) ((distTime.getTime() - today.getTime().getTime()) / nd);
        if(day>=0&&day<=dayNames.length){
            dateTime=dayNames[day]+"("+dateTime+")";
        }
        return dateTime+" "+DateUtils.parseDateToStr("HH:mm", distTime);
    }

    @Override
    public String getPickDateTime(Shop shop, Long pointId) {
        if(null==shop){
            throw  new CustomException("商铺不存在！");
        }
        DistributionPoint point=distributionPointMapper.selectDistributionPointById(pointId);
        if(null==point){
            return "";
        }
        List<DateDto> dateList= null;
        try {
            dateList = this.getDistributionDateList(shop,point);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(CollectionUtils.isEmpty(dateList)){
            return "";
        }
        List<TimeDto> timeList=dateList.get(0).getTimeList();
        return dateList.get(0).getDayTime()+" "+timeList.get(0).getStartTime();
    }

    @Override
    public String getPickDateTime(Shop shop, DistributionPointDto pointDto) {
        if(null==shop){
            throw  new CustomException("商铺不存在！");
        }
        if(null==pointDto){
            return "";
        }
        List<DateDto> dateList= null;
        try {
            dateList = this.getDistributionDateList(shop,pointDto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(CollectionUtils.isEmpty(dateList)){
            return "";
        }
        List<TimeDto> timeList=dateList.get(0).getTimeList();
        return dateList.get(0).getDayTime()+" "+timeList.get(0).getStartTime();
    }

    public Date getDistributionDate(Double distance, String distType){
        DistTime distTime=ordersDistService.getDistTimeConfig(distType);
        //划分时间之前下单的配送时间
        if(DateUtils.getNowDate().before(ordersDistService.getTime(distTime.getDivide()))){
           return ordersDistService.getTime(distTime.getBefore());
        }else{//划分时间之后下单的配送时间
           return ordersDistService.getTime(distTime.getAfter());
        }
    }
    /**
     * 查询集合匹配的对象与当前索引
     *
     * @param dayTime
     * @return
     */
    private DateDto getDateTimeDtoDayTime(List<DateDto> list, String dayTime) {
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getDayTime().equals(dayTime)) {
                    list.get(i).setIndex(i);
                    return list.get(i);
                }
            }
        }
        return null;
    }

    private BigDecimal calcDateTimePrice(String distTime, List<DistributionConfig> distributionConfigList) {
        BigDecimal discPrice = new BigDecimal(0);
        String[] currentSplit = distTime.split(":");
        int currentTime = Integer.valueOf(currentSplit[0]) * 3600 + Integer.valueOf(currentSplit[1]) * 60;
        String[] minSplit, maxSplit = null;
        int minTime, maxTime = 0;

        for (DistributionConfig distributionConfig : distributionConfigList) {
            //时间运费
            if (distributionConfig.getType().equals("30")) {
                minSplit = distributionConfig.getMin().split(":");
                minTime = Integer.valueOf(minSplit[0]) * 3600 + Integer.valueOf(minSplit[1]) * 60;
                maxSplit = distributionConfig.getMax().split(":");
                maxTime = Integer.valueOf(maxSplit[0]) * 3600 + Integer.valueOf(maxSplit[1]) * 60;
                if (currentTime > minTime || currentTime < maxTime) {
                    discPrice = discPrice.add(distributionConfig.getPrice());
                }
            }
        }
        return discPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

}
